<?php
/**
 * Created by PhpStorm.
 * User: LiWenYe
 * Date: 2020/5/12
 */
namespace App\Support\Table;

class Column
{
    /**
     * @var string 名称
     */
    public $name = '';

    /**
     * @var string 字段
     */
    public $field = '';

    /**
     * @var string 保存字段
     */
    public  $saveField = '';

    /**
     * @var mixed 值
     */
    public $value;

    /**
     * @var string 类型
     */
    public $type = self::TYPE_STRING;

    /**
     * @var string 列表类型
     */
    public $listType = self::TYPE_STRING;

    /**
     * @var string[] 操作
     */
    public $actions = [];

    /**
     * @var int 显示状态
     * 转换成二进制 7 => 111
     * 三个1分别对应 列表 编辑 添加 的显示状态 0隐藏 1显示
     */
    public $showStatus = 7;

    /**
     * @var bool 是否必须
     */
    public $isRequired = false;

    /**
     * @var string 默认值
     */
    public $default = null;

    /**
     * @var string 提示信息
     */
    public $hint = '';

    /**
     * @var array 选项
     */
    public $options = [];

    /**
     * @var string 格式化
     */
    public $format = '';

    /**
     * @var array 操作
     */
    public $operations = [];

    const TYPE_INT       = 'int';
    const TYPE_STRING    = 'string';
    const TYPE_FLOAT     = 'float';
    const TYPE_IMAGE     = 'image';
    const TYPE_IMAGES    = 'images';
    const TYPE_FILE      = 'file';
    const TYPE_FILES     = 'files';
    const TYPE_SELECT    = 'select';
    const TYPE_CASCADE   = 'cascade';
    const TYPE_CHECKBOX  = 'checkbox';
    const TYPE_TIMESTAMP = 'timestamp';
    const TYPE_DATETIME  = 'datetime';
    const TYPE_RADIO     = 'radio';
    const TYPE_SWITCH    = 'switch';
    const TYPE_SLIDER    = 'slider';
    const TYPE_TEXTAREA  = 'textarea';
    const TYPE_MARKDOWN  = 'markdown';
    const TYPE_JSON      = 'json';

    const TYPE_NAMES = [
        self::TYPE_INT,
        self::TYPE_STRING,
        self::TYPE_FLOAT,
        self::TYPE_IMAGE,
        self::TYPE_IMAGES,
        self::TYPE_FILE,
        self::TYPE_FILES,
        self::TYPE_SELECT,
        self::TYPE_CASCADE,
        self::TYPE_CHECKBOX,
        self::TYPE_RADIO,
        self::TYPE_SWITCH,
        self::TYPE_TIMESTAMP,
        self::TYPE_DATETIME,
        self::TYPE_SLIDER,
        self::TYPE_TEXTAREA,
        self::TYPE_MARKDOWN,
        self::TYPE_JSON,
    ];

    /**
     * @var array 特征
     * sortable:排序
     * editable:列表编辑
     * fixed:固定位置
     * disabled:不能编辑
     */
    public $traits = [];

    /**
     * 设置选项
     * @param $options
     * @return Column
     * @author LiWenYe
     */
    public function setOptions($options)
    {
        $this->options = $options;
        return $this;
    }

    /**
     * 解析字段信息
     * @param $field
     * @param $rule
     * @return $this
     * @author LiWenYe
     */
    public function parse($field, $rule)
    {
        $this->saveField = $this->field = $field;
        $explode = explode('|', $rule);
        $this->actions = [];
        foreach ($explode as $item) {
            $type = explode(':', $item);
            $params = $type;
            $action = $type[0];

            $param = '';
            if (isset($type[1])) {
                unset($params[0]);
                $param = implode(':', $params);
            }
            if (strpos($action, '[') === 0) {
                $param = str_replace(['[', ']'], '', $action);
                $action = 'name';
            }

            $this->actions[$action] = $param;
            if (in_array($action, self::TYPE_NAMES)) {
                $this->type = $action;
                $this->listType = $action;
            }

            if (method_exists($this, $action)) {
                $this->$action($param);
            }
        }
        return $this;
    }

    public function field($param)
    {
        $this->field = $param;
        return $this;
    }

    public function name($param)
    {
        $this->name = $param;
        return $this;
    }

    public function show($param)
    {
        $this->showStatus = (int)$param;
        return $this;
    }

    public function format($param)
    {
        $this->format = $param;
        return $this;
    }

    public function traits($param)
    {
        $this->traits = explode(',', $param);
        return $this;
    }

    public function slider($param)
    {
        if ($param) {
            $options = explode(',', $param);
            $sliderOptionLabels = ['min', 'max', 'step'];
            foreach ($options as $index => $option) {
                $option = explode('[', rtrim($option, ']'));
                if ($option[0] !== '') {
                    $this->options[] = [
                        'label' => $option[1] ?? ($sliderOptionLabels[$index] ?? ''),
                        'value' => (float)$option[0]
                    ];
                }
            }
        }
        return $this;
    }

    public function int($param)
    {
        return $this->slider($param);
    }

    public function float($param)
    {
        return $this->slider($param);
    }

    public function select($param)
    {
        if ($param) {
            $options = explode(',', $param);
            foreach ($options as $index => $option) {
                $option = explode('[', rtrim($option, ']'));
                empty($option[0]) && $option[0] = $index;
                $this->options[$option[0]] = $option[1] ?? '';
            }
        }
        return $this;
    }

    public function radio($param)
    {
        return $this->select($param);
    }

    public function switch($param)
    {
        if ($param) {
            $options = explode(',', $param);
            $sliderOptionLabels = ['false', 'true'];
            foreach ($options as $index => $option) {
                $option = explode('[', rtrim($option, ']'));
                $this->options[$option[0]] = $option[1] ?? ($sliderOptionLabels[$index] ?? '');
            }
            return $this;
        } else {
            $this->options[] = [
                [
                    'label' => 'true',
                    'value' => true,
                ],
                [
                    'label' => 'false',
                    'value' => false,
                ]
            ];
            return $this;
        }
    }

    public function required()
    {
        $this->isRequired = true;
        return $this;
    }

    public function default($param)
    {
        if (is_numeric($param) && strpos($param, '.') === false) {
            // 整数强制转换
            $this->default = (int)$param;
        } elseif ($this->type === self::TYPE_SWITCH) {
            if ($param == 'false') {
                $this->default = false;
            } elseif ($param == 'true') {
                $this->default = true;
            } else {
                $this->default = $param;
            }
        } else {
            // 小数也用字符串
            $this->default = $param;
        }
        return $this;
    }

    public function hint($param)
    {
        $this->hint = $param;
    }
}
